using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TMPro;
using Unity.Passport.Runtime;
using System.Threading.Tasks;
using Entitlement;
using Google.Protobuf;
using Passport;
using Unity.Passport.Runtime.UI;

namespace Unity.Passport.Sample.Scripts
{
    public enum PassType
    {
        Free = 0,
        Golden = 1,
    }

    // 一个战令信息存储
    // PassItem 是 EntitlementItem 的一种具体类型
    public class PassItem
    {
        public EntitlementItem PassItemInfo;
        public string Desc;
        public List<RewardItem> RewardItems;
        public List<RewardItem.Config> RewardItemsConfig;
    }

    public class EntitlementUIController : MonoBehaviour
    {
        // 战令等级和经验值
        public List<Slider> levelSliderList; // 战令等级滑动条
        public List<TextMeshProUGUI> levelTextList; // 战令等级文本
        public List<Slider> experienceSliderList; // 经验值
        private const float MaxExperience = 100;

        // 战令解锁样式相关
        public Transform sliderCounts;
        public Sprite lockCountIcon;
        public Sprite unlockCountIcon;

        // golden pass 徽章样式
        public List<Image> goldenPassImages;
        public List<GameObject> goldenPassLocks;
        private readonly Color _lockedColor = new Color(0.6f, 0.6f, 0.6f, 1);
        private readonly Color _unlockedColor = new Color(1, 1, 1, 1);
        public List<GameObject> goldenPassLights; // 光效

        private int _level;
        private readonly int _maxLevel = 13; // 0-13，共 14个等级

        public Transform goldenPass;
        public Transform freePass;
        public Button purchaseButton; // 购买按钮
        public Button upgradeButton; // 升级按钮
        public GameObject purchasePanel; // 购买面板
        public RectTransform rewardScrollRectContent; // 奖项面板滚动
        private bool _purchased; // 是否已经购买

        // 奖励相关 UI
        private const int InitialCount = 999;
        private int _energy = InitialCount;
        private int _gold = InitialCount;
        private int _gem = InitialCount;
        public List<TextMeshProUGUI> energy;
        public List<TextMeshProUGUI> gold;
        public List<TextMeshProUGUI> gem;
        public GameObject rewardItemPrefab;
        public Transform rewardGetList; // 得到的奖品展示
        public GameObject rewardGetItemPrefab;
        public GameObject rewardGetPanel;

        private bool _initFinished;

        #region Private Fields for Pass

        private const string Namespace = "Pass"; // 战令 Entitlement

        private readonly Dictionary<PassType, PassItem> _passDictionary = new()
        {
            {
                PassType.Free, new()
                {
                    Desc = "Free",
                    RewardItems = new(),
                    RewardItemsConfig = new()
                    {
                        new()
                        {
                            Type = RewardItem.RewardType.Gold,
                            Count = 1000,
                        },
                        new()
                        {
                            Type = RewardItem.RewardType.Gem,
                            Count = 1000,
                        },
                        new()
                        {
                            Type = RewardItem.RewardType.Energy,
                            Count = 10,
                        },
                        new()
                        {
                            Type = RewardItem.RewardType.Gold,
                            Count = 300,
                        },
                        new()
                        {
                            Type = RewardItem.RewardType.Gold,
                            Count = 1000,
                        },
                        new()
                        {
                            Type = RewardItem.RewardType.Glove,
                            Count = 5,
                        },
                        new()
                        {
                            Type = RewardItem.RewardType.Energy,
                            Count = 20,
                        },
                        new()
                        {
                            Type = RewardItem.RewardType.Gold,
                            Count = 3000,
                        },
                        new()
                        {
                            Type = RewardItem.RewardType.Gold,
                            Count = 1000,
                        },
                        new()
                        {
                            Type = RewardItem.RewardType.Glove,
                            Count = 5,
                        },
                        new()
                        {
                            Type = RewardItem.RewardType.Glove,
                            Count = 5,
                        },
                        new()
                        {
                            Type = RewardItem.RewardType.Gold,
                            Count = 3000,
                        },
                        new()
                        {
                            Type = RewardItem.RewardType.Gem,
                            Count = 1000,
                        },
                        new()
                        {
                            Type = RewardItem.RewardType.Glove,
                            Count = 5,
                        },
                    }
                }
            },
            {
                PassType.Golden, new()
                {
                    Desc = "Golden",
                    RewardItems = new(),
                    RewardItemsConfig = new()
                    {
                        new()
                        {
                            Type = RewardItem.RewardType.Gold,
                            Count = 2000,
                        },
                        new()
                        {
                            Type = RewardItem.RewardType.Gem,
                            Count = 2000,
                        },
                        new()
                        {
                            Type = RewardItem.RewardType.Energy,
                            Count = 20,
                        },
                        new()
                        {
                            Type = RewardItem.RewardType.Target,
                            Count = 800,
                        },
                        new()
                        {
                            Type = RewardItem.RewardType.Gold,
                            Count = 3000,
                        },
                        new()
                        {
                            Type = RewardItem.RewardType.Clover,
                            Count = 20,
                        },
                        new()
                        {
                            Type = RewardItem.RewardType.Energy,
                            Count = 20,
                        },
                        new()
                        {
                            Type = RewardItem.RewardType.Gold,
                            Count = 6000,
                        },
                        new()
                        {
                            Type = RewardItem.RewardType.Gold,
                            Count = 2000,
                        },
                        new()
                        {
                            Type = RewardItem.RewardType.Clover,
                            Count = 5,
                        },
                        new()
                        {
                            Type = RewardItem.RewardType.Glove,
                            Count = 15,
                        },
                        new()
                        {
                            Type = RewardItem.RewardType.Gold,
                            Count = 5000,
                        },
                        new()
                        {
                            Type = RewardItem.RewardType.Gem,
                            Count = 8000,
                        },
                        new()
                        {
                            Type = RewardItem.RewardType.Glove,
                            Count = 25,
                        },
                    }
                }
            }
        };

        #endregion

        private Persona Persona => DemoUIController.Instance.Persona;

        /// <summary>
        /// 获取战令等级
        /// </summary>
        private async Task GetLevel()
        {
            Persona.Properties.TryGetValue("level", out string level);

            // 兼容旧数据
            if (level == null)
            {
                level = "0"; // 默认值
                Persona.Properties.Add("level", level);
        
                await PassportSDK.Identity.UpdatePersona(Persona.DisplayName, Persona.IconUrl, new Dictionary<string, string>
                {
                    {"level", "0"}
                });
            }

            _level = int.Parse(level);
        }

        private float GetExperience(int level)
        {
            return level == _maxLevel ? MaxExperience * level - 1 : MaxExperience * level;
        }

        /// <summary>
        /// 显示战令等级
        /// </summary>
        private async void ShowLevel(bool initial = false)
        {
            await GetLevel();
            foreach (var item in levelSliderList)
            {
                item.value = _level;
            }

            var nextExperience = GetExperience(_level);
            foreach (var item in experienceSliderList)
            {
                item.GetComponent<SliderController>().SetValue(nextExperience, !initial, () =>
                {
                    foreach (var item in levelTextList)
                    {
                        int levelShown = _level + 1;
                        item.text = levelShown.ToString();
                    }
                });
            }


            upgradeButton.interactable = _level < _maxLevel;

            SetUnlockStyle();
        }

        /// <summary>
        /// 升级
        /// </summary>
        public async void Upgrade()
        {
            if (_level >= _maxLevel)
            {
                upgradeButton.interactable = false;
                return;
            }

            _level += 1;
            Persona.Properties["level"] = _level.ToString();
            await PassportSDK.Identity.UpdatePersona(Persona.DisplayName, Persona.IconUrl, new Dictionary<string, string>()
            {
                {"level", _level.ToString()}
            });
            ShowLevel();

            if (_level >= _maxLevel)
            {
                upgradeButton.interactable = false;
            }
        }

        /// <summary>
        /// 设置奖励项的解锁样式
        /// </summary>
        /// <param name="type"></param>
        private void SetUnlockStyleForRewardItems(PassType type)
        {
            var list = _passDictionary[type].RewardItems;
            for (int i = 0; i < list.Count; i += 1)
            {
                var child = list[i];
                if (child != null)
                {
                    if (_level >= i)
                    {
                        child.Upgrade();
                    }
                }
            }
        }

        /// <summary>
        /// 根据当前等级设置战令解锁样式
        /// </summary>
        private void SetUnlockStyle()
        {
            for (int i = 0; i < sliderCounts.childCount; i += 1)
            {
                var img = sliderCounts.GetChild(i).gameObject.GetComponent<Image>();
                img.sprite = _level >= i ? unlockCountIcon : lockCountIcon;
            }

            // 根据等级设置 pass 奖励项的解锁样式
            SetUnlockStyleForRewardItems(PassType.Free);
            SetUnlockStyleForRewardItems(PassType.Golden);
        }


        /// <summary>
        /// 购买指定 type 的 pass
        /// </summary>
        private async Task Purchase(PassType passType)
        {
            var createRequest = new CreateEntitlementRequest()
            {
                PersonaId = Persona.PersonaID,
                Namespace = Namespace,
                Type = _passDictionary[passType].Desc,
                Tag = "",
                Consumable = true,
                LimitCount = (uint)_maxLevel + 1,
            };
            var reqData = JsonFormatter.Default.Format(createRequest);
            var response = await MockServer.Instance.CreateEntitlement(reqData);
            if (response == null)
            {
                throw new Exception("Failed to create.");
            }

            var info = response.Entitlement;
            _passDictionary[passType].PassItemInfo = info; // 储存信息
        }

        /// <summary>
        /// 购买 golden pass
        /// </summary>
        public async void PurchaseGoldenPass()
        {
            try
            {
                await Purchase(PassType.Golden);
                UnlockGoldenPassUI();
                purchasePanel.SetActive(false);
            }
            catch (Exception e)
            {
                Debug.Log(e.Message);
            }
        }

        public void ShowPurchasePanel()
        {
            if (_purchased) return;
            purchasePanel.SetActive(true);
        }

        /// <summary>
        /// 设置 golden pass 解锁样式
        /// </summary>
        private void UnlockGoldenPassUI()
        {
            purchaseButton.interactable = false;
            _purchased = true;
            var list = _passDictionary[PassType.Golden].RewardItems;
            foreach (var pass in list)
            {
                pass.Unlock();
            }

            SetGoldenIconStyle(false);
        }

        /// <summary>
        /// 设置 Golden Pass Icon 解锁样式
        /// </summary>
        /// <param name="locked"></param>
        private void SetGoldenIconStyle(bool locked)
        {
            // 设置 golden pass 徽章样式
            foreach (var lockObj in goldenPassLocks)
            {
                lockObj.SetActive(locked);
            }

            foreach (var img in goldenPassImages)
            {
                img.color = locked ? _lockedColor : _unlockedColor;
            }

            foreach (var lightObj in goldenPassLights)
            {
                lightObj.SetActive(!locked);
            }
        }

        /// <summary>
        /// 设置 free pass 解锁样式
        /// </summary>
        private void UnlockFreePassUI()
        {
            var list = _passDictionary[PassType.Free].RewardItems;
            foreach (var pass in list)
            {
                pass.Unlock();
            }
        }

        /// <summary>
        /// 获取战令创建、消费数据并设置样式
        /// </summary>
        private async Task InitPass()
        {
            try
            {
                // 查询 free pass 是否已创建、已消费数量
                var freeResult = await PassportFeatureSDK.Entitlement.QueryEntitlement(Namespace, PassType.Free.ToString());
                if (!freeResult.Success)
                {
                    try
                    {
                        await Purchase(PassType.Free);
                        UnlockFreePassUI();
                    }
                    catch (Exception e)
                    {
                        Debug.Log(e);
                    }
                }
                else
                {
                    UnlockFreePassUI();
                    var item = freeResult.Entitlement;
                    _passDictionary[PassType.Free].PassItemInfo = item;
                    // 设置已消费样式
                    var consumedCount = item.LimitCount - item.RemainingCount;

                    SilentlyGetAward(0, (int)consumedCount - 1, PassType.Free);
                }
                
                // 查询 golden pass 是否已创建、已消费数量
                var goldenResult = await PassportFeatureSDK.Entitlement.QueryEntitlement(Namespace, PassType.Golden.ToString());
                if (goldenResult.Success)
                {
                    var item = goldenResult.Entitlement;
                    _passDictionary[PassType.Golden].PassItemInfo = item;

                    // 已购买按钮不可点击
                    purchaseButton.interactable = false;
                    _purchased = true;
                    
                    // 设置解锁样式
                    UnlockGoldenPassUI();
                    
                    // 设置已消费样式
                    var consumedCount = item.LimitCount - item.RemainingCount;
                    SilentlyGetAward(0, (int)consumedCount - 1, PassType.Golden);
                }
                else
                {
                    purchaseButton.interactable = true;
                    _purchased = false;
                }
            }
            catch (PassportException e)
            {
                Debug.Log(e.Code);
                Debug.Log(e.Message);
            }
        }

        /// <summary>
        /// 设置消费监听
        /// </summary>
        private void AddListenerForConsume(PassType type)
        {
            var list = _passDictionary[type].RewardItems;
            for (int i = 0; i < list.Count; i += 1)
            {
                var index = i;
                list[i].consume.AddListener(() => { ConsumeHandler(type, index); });
            }
        }

        /// <summary>
        /// 处理消费事件
        /// </summary>
        /// <param name="type"></param>
        /// <param name="index"></param>
        private async void ConsumeHandler(PassType type, int index)
        {
            // 查看已消费数量
            var pass = _passDictionary[type].PassItemInfo;
            var consumedCount = pass.LimitCount - pass.RemainingCount;

            uint countToConsume = (uint)(index - consumedCount + 1);
            if (countToConsume <= 0)
            {
                Debug.LogError("countToConsume <= 0");
                return;
            }

            try
            {
                //  消费并更新数据
                _passDictionary[type].PassItemInfo =
                    await PassportFeatureSDK.Entitlement.ConsumeEntitlement(pass.Id, pass.ResourceAge, countToConsume);

                SetConsumedStyle((int)consumedCount, index, type);
            }
            catch (PassportException e)
            {
                UIMessage.Show(e);
            }

        }

        /// <summary>
        /// 静默领取奖励，更新数据
        /// </summary>
        /// <param name="startIndex"></param>
        /// <param name="endIndex"></param>
        /// <param name="type"></param>
        private void SilentlyGetAward(int startIndex, int endIndex, PassType type)
        {
            var list = _passDictionary[type].RewardItems;

            for (int i = startIndex; i <= endIndex && i < list.Count; i += 1)
            {
                var item = list[i];
                var config = item.ItemConfig;
                var gotCount = item.Claimed();

                switch (config.Type)
                {
                    case RewardItem.RewardType.Gold:
                        _gold += gotCount;
                        break;
                    case RewardItem.RewardType.Energy:
                        _energy += gotCount;
                        break;
                    case RewardItem.RewardType.Gem:
                        _gem += gotCount;
                        break;
                }
            }

            // 检查状态
            SetStatusBar();
        }

        /// <summary>
        /// 设置消费样式
        /// </summary>
        /// <param name="startIndex"></param>
        /// <param name="endIndex"></param>
        /// <param name="type"></param>
        private void SetConsumedStyle(int startIndex, int endIndex, PassType type)
        {
            var list = _passDictionary[type].RewardItems;
            Dictionary<RewardItem.RewardType, int> GotCountMap = new()
            {
                { RewardItem.RewardType.Gold, 0 },
                { RewardItem.RewardType.Energy, 0 },
                { RewardItem.RewardType.Gem, 0 },
                { RewardItem.RewardType.Clover, 0 },
                { RewardItem.RewardType.Glove, 0 },
                { RewardItem.RewardType.Target, 0 },
            };
            for (int i = startIndex; i <= endIndex && i < list.Count; i += 1)
            {
                var item = list[i];
                var config = item.ItemConfig;
                var gotCount = item.Claimed();

                GotCountMap[config.Type] += gotCount;
                switch (config.Type)
                {
                    case RewardItem.RewardType.Gold:
                        _gold += gotCount;
                        break;
                    case RewardItem.RewardType.Energy:
                        _energy += gotCount;
                        break;
                    case RewardItem.RewardType.Gem:
                        _gem += gotCount;
                        break;
                }
            }

            // 生成奖项列表
            foreach (KeyValuePair<RewardItem.RewardType, int> kvp in GotCountMap)
            {
                if (kvp.Value != 0)
                {
                    var item = Instantiate(rewardGetItemPrefab, rewardGetList);
                    item.GetComponent<RewardItem>().Init(new RewardItem.Config()
                    {
                        Type = kvp.Key,
                        Count = kvp.Value
                    });
                }
            }

            rewardGetPanel.SetActive(true);
        }

        public void HideRewardGetPanel()
        {
            rewardGetPanel.SetActive(false);
            // 清空对象
            for (int i = 0; i < rewardGetList.childCount; i += 1)
            {
                Destroy(rewardGetList.GetChild(i).gameObject);
            }

            SetStatusBar();
        }

        /// <summary>
        /// 设置顶部状态栏信息
        /// </summary>
        private void SetStatusBar()
        {
            foreach (var item in energy)
            {
                item.text = _energy.ToString();
            }

            foreach (var item in gem)
            {
                item.text = _gem.ToString();
            }

            foreach (var item in gold)
            {
                item.text = _gold.ToString();
            }
        }

        private void GenRewardItems(PassType type)
        {
            var configs = _passDictionary[type].RewardItemsConfig;
            var list = _passDictionary[type].RewardItems;
            var parent = type == PassType.Free ? freePass : goldenPass;
            foreach (var config in configs)
            {
                var obj = Instantiate(rewardItemPrefab, parent);
                var controller = obj.GetComponent<RewardItem>();
                list.Add(controller);
                controller.Init(config);
            }
        }

        /// <summary>
        /// 初始化战令状态
        /// </summary>
        public void Init()
        {
            if (MockServer.Instance == null)
            {
                MockServer.InitInstance();
            }
            if (!_initFinished)
            {
                _initFinished = true;
                // 初始化UI对象列表
                GenRewardItems(PassType.Free);
                GenRewardItems(PassType.Golden);
                
                AddListenerForConsume(PassType.Free);
                AddListenerForConsume(PassType.Golden);
            }

            ResetData();
        }

        /// <summary>
        /// 重置数据
        /// </summary>
        private async void ResetData()
        {
            // 重置 rewards 样式
            ResetAwardItems(PassType.Free);
            ResetAwardItems(PassType.Golden);

            // 重置经验值
            foreach (var item in experienceSliderList)
            {
                item.maxValue = MaxExperience;
                item.value = 0;
            }

            // 重置位置
            var pos = rewardScrollRectContent.anchoredPosition;
            rewardScrollRectContent.anchoredPosition = new Vector2(0, pos.y);

            // 重置上锁样式
            SetGoldenIconStyle(true);

            // 重置状态栏
            _gem = InitialCount;
            _energy = InitialCount;
            _gold = InitialCount;
            SetStatusBar();

            // 显示等级
            ShowLevel(true);

            // 查询 pass 状态
            await InitPass();
        }

        /// <summary>
        /// 重置奖励项数据
        /// </summary>
        /// <param name="type"></param>
        private void ResetAwardItems(PassType type)
        {
            var list = _passDictionary[type].RewardItems;
            foreach (var item in list)
            {
                item.ResetItem();
            }
        }
    }
}